package com.rizzo.analytics.domain.performance;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.rizzo.infrastructure.web.validator.Save;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import javax.validation.Valid;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;

public class Performance implements Serializable {

	private static final long serialVersionUID = 8L;

	@Valid
	@Size(min = 1, message = "performance.monitored.services.empty", groups = {Save.class})
	private List<MonitoredService> monitoredServices;

	public Performance() {
	}

	public Performance(List<MonitoredService> monitoredServices) {
		this.monitoredServices = monitoredServices;
	}

	public List<MonitoredService> getMonitoredServices() {
		if (monitoredServices == null) {
			monitoredServices = Lists.newArrayList();
		}
		return monitoredServices;
	}

	public void setMonitoredServices(List<MonitoredService> monitoredServices) {
		this.monitoredServices = monitoredServices;
	}

	public void addMonitoredService(MonitoredService monitoredService) {
		if (monitoredServices == null) {
			monitoredServices = Lists.newArrayList();
		}
		monitoredServices.add(monitoredService);
	}

	public MonitoredService getMonitoredService(final String service, final String instanceName, final String instanceIndex) {
		Predicate<MonitoredService> isService = new Predicate<MonitoredService>() {

			@Override
			public boolean apply(MonitoredService trendedService) {
				boolean serviceEquals = trendedService.getService().equals(service);
				boolean instanceEquals = trendedService.getInstanceName().equals(instanceName) && trendedService.getInstanceIndex().equals(instanceIndex);
				return serviceEquals && instanceEquals;
			}

		};
		Iterable<MonitoredService> filteredService = Iterables.filter(getMonitoredServices(), isService);
		return Iterables.getFirst(filteredService, null);
	}

	public void merge(Performance update) {
		for (MonitoredService monitoredService : update.getMonitoredServices()) {
			MonitoredService currentService =
					getMonitoredService(monitoredService.getService(), monitoredService.getInstanceName(), monitoredService.getInstanceIndex());
			currentService.getCalls().addAll(monitoredService.getCalls());
			currentService.setTotalCalls(monitoredService.getTotalCalls());
		}
	}

	@Override
	public boolean equals(Object o) {
		return EqualsBuilder.reflectionEquals(this, o);
	}

	@Override
	public int hashCode() {
		return HashCodeBuilder.reflectionHashCode(this);
	}

	@Override
	public String toString() {
		return new ToStringBuilder(this).
				append("monitoredServices", monitoredServices).
				toString();
	}
}
